<!--
 * @Author: your name
 * @Date: 2021-11-12 10:48:07
 * @LastEditTime: 2021-11-12 11:42:40
 * @LastEditors: Please set LastEditors
 * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 * @FilePath: /my-draw/src/custom-layer-webgl2-1112.vue
-->
<script setup lang="ts">
// import geojsonvt from 'geojson-vt'
import mapboxgl from 'mapbox-gl'
import { onMounted } from 'vue'
let map: any = null

const initMapFn = (): void => {
  mapboxgl.accessToken =
    'pk.eyJ1Ijoic2FnaXQtemgiLCJhIjoiY2t0bnl5dDFnMDZ0aTJwcDNsa3N4emF1biJ9.jFO8rJJN-kvaz9vuQ0odKQ'
  const mapOptions = {
    container: 'map',
    zoom: 3,
    center: [7.5, 58],
    // style: 'mapbox://styles/mapbox/light-v10'
    style: 'mapbox://styles/mapbox/streets-v11',

  }

  // 给 mapboxgl 适配 webgl2版本
  // if (mapboxgl.Map.prototype._setupPainter.toString().indexOf("webgl2") == -1) {
  //   var _setupPainter_old = mapboxgl.Map.prototype._setupPainter;
  //   mapboxgl.Map.prototype._setupPainter = function () {
  //     var getContext_old = this._canvas.getContext;
  //     this._canvas.getContext = (name: string, attrib: any) => {
  //       return getContext_old.apply(this, ["webgl2", attrib]) ||
  //         getContext_old.apply(this, ['webgl', attrib]) ||
  //         getContext_old.apply(this, ['experimental-webgl', attrib]);
  //     }
  //     _setupPainter_old.apply(this);
  //     this._canvas.getContext = getContext_old;
  //   };
  // }

  map = new mapboxgl.Map(mapOptions)

  const layer = new TestLayer()
  console.log(layer);
  map.on('load', () => {
    console.log(3333);


    map.addLayer(layer, 'zhx')
    const layers = map.getStyle().layers
    console.log(layers.filter(l => l.type === 'custom'))

  })

}

class TestLayer {
  public id // 图层id
  public type // 写死，必须为 custom
  public renderingMode //2d 或3d
  public program: WebGLProgram | null = null // WebGLProgram
  public vao = {} // 顶点对象

  constructor(options?: any) {
    this.id = 'TestLayer';//图层id
    this.type = 'custom'; //写死，必须为该值
    this.renderingMode = '3d';//2d 或3d
  }
  // method called when the layer is added to the map
  // https://docs.mapbox.com/mapbox-gl-js/api/#styleimageinterface#onadd
  onAdd(map: any, gl: WebGLRenderingContext) {
    //定义三个点坐标，每个点都是 经度 纬度 高度
    const coors = [
      25.004, 60.239, 0,
      13.403, 52.562, 1000,
      30.498, 50.541, 2000
    ];

    //定义着色器代码
    // 顶点着色器
    const vs = `#version 300 es
                    uniform mat4 u_matrix;
                    layout(location=0) in vec3 a_pos;
                    void main() {
                        gl_Position = u_matrix * vec4(a_pos, 1.0);
                    }`;
    // 片源着色器
    const fs = `#version 300 es
                    precision highp float;
                    out vec4 outColor;
                    void main() {
                        outColor = vec4(1.0, 0.0, 0.0, 0.5);
                    }`;

    //创建着色器
    var vertexShader = gl.createShader(gl.VERTEX_SHADER);
    gl.shaderSource(vertexShader!, vs);
    gl.compileShader(vertexShader!);

    var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
    gl.shaderSource(fragmentShader!, fs);
    gl.compileShader(fragmentShader!);

    //创建program并link着色器
    this.program = gl.createProgram();
    gl.attachShader(this.program!, vertexShader!);
    gl.attachShader(this.program, fragmentShader);
    gl.linkProgram(this.program);

    //将三角形经纬度点转墨卡托投影，mapboxgl提供了墨卡托坐标转webgl裁剪坐标系的转换矩阵
    const positions = new Float32Array(coors.length);
    for (let i = 0; i < coors.length; i = i + 3) {
      const mkt_coor = mapboxgl.MercatorCoordinate.fromLngLat({
        lng: coors[i],
        lat: coors[i + 1]
      }, coors[i + 2]);
      positions[i] = mkt_coor.x;
      positions[i + 1] = mkt_coor.y;
      positions[i + 2] = mkt_coor.z;
    }

    //创建vao对象绑定顶点
    this.vao = gl.createVertexArray();
    gl.bindVertexArray(this.vao);

    //创建buffer
    let buffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
    gl.bufferData(
      gl.ARRAY_BUFFER,
      positions,
      gl.STATIC_DRAW
    );
    gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
    gl.enableVertexAttribArray(0);

    //绑定结束记得一定要设置 null，释放资源，不然地图出不来
    gl.bindBuffer(gl.ARRAY_BUFFER, null);
    gl.bindVertexArray(null);
  }

  render(gl: WebGLRenderingContext, matrix: Array<number>) {
    // 启用 program
    gl.useProgram(this.program);

    // 绑定 vao 顶点对象
    gl.bindVertexArray(this.vao);

    // uniform赋值，将转换矩阵传入着色器
    gl.uniformMatrix4fv(
      gl.getUniformLocation(this.program, 'u_matrix'),
      false,
      matrix
    );

    // 启用混色
    gl.enable(gl.BLEND);
    gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);

    // 绘制
    gl.drawArrays(gl.TRIANGLE_STRIP, 0, 3);

    // 释放绑定的vao，必须写
    gl.bindVertexArray(null);
  }

  onRemove(map: any, gl: WebGLRenderingContext) {
    /*
        根据实际情况将定义的webgl对象删掉，以下为回收资源的webgl api
        gl.deleteBuffer()
        gl.deleteFramebuffer()
        gl.deleteProgram()
        gl.deleteRenderbuffer()
        gl.deleteShader()
        gl.deleteTexture()
    */
    gl.deleteProgram(this.program);
  }
};

onMounted(() => initMapFn())



</script>

<template>
  <div id="map"></div>
</template>

<style>
#map {
  width: 1000px;
  height: 500px;
}
</style>